package com.googlecode.mvcguice.routing;

import static com.google.common.base.Defaults.defaultValue;

import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import com.google.inject.AbstractModule;
import com.googlecode.mvcguice.Method;

public abstract class RoutesModule extends AbstractModule {
	private final RoutesModuleBuilder routesModuleBuilder = new RoutesModuleBuilder();

	@Override
	protected final void configure() {
		configureRoutes();
		install(routesModuleBuilder);
	}

	protected abstract void configureRoutes();

	protected final MethodBindingBuilder serve(String urlPattern) {
		return routesModuleBuilder.serve(urlPattern);
	}

	protected final byte byteVar(String name) {
		routesModuleBuilder.captureVar(Byte.class, name);
		return defaultValue(byte.class);
	}

	protected final short shortVar(String name) {
		routesModuleBuilder.captureVar(Short.class, name);
		return defaultValue(short.class);
	}

	protected final int intVar(String name) {
		routesModuleBuilder.captureVar(Integer.class, name);
		return defaultValue(int.class);
	}

	protected final long longVar(String name) {
		routesModuleBuilder.captureVar(Long.class, name);
		return defaultValue(long.class);
	}

	protected final float floatVar(String name) {
		routesModuleBuilder.captureVar(Float.class, name);
		return defaultValue(float.class);
	}

	protected final double doubleVar(String name) {
		routesModuleBuilder.captureVar(Double.class, name);
		return defaultValue(double.class);
	}

	protected final char charVar(String name) {
		routesModuleBuilder.captureVar(Character.class, name);
		return defaultValue(char.class);
	}

	protected final boolean booleanVar(String name) {
		routesModuleBuilder.captureVar(Boolean.class, name);
		return defaultValue(boolean.class);
	}

	protected final String stringVar(String name) {
		routesModuleBuilder.captureVar(String.class, name);
		return "";
	}

	//TODO: add arrays support
	protected final byte byteParam(String name) {
		routesModuleBuilder.captureSimpleParam(Byte.class, name);
		return defaultValue(byte.class);
	}

	protected final short shortParam(String name) {
		routesModuleBuilder.captureSimpleParam(Short.class, name);
		return defaultValue(short.class);
	}

	protected final int intParam(String name) {
		routesModuleBuilder.captureSimpleParam(Integer.class, name);
		return defaultValue(int.class);
	}

	protected final long longParam(String name) {
		routesModuleBuilder.captureSimpleParam(Long.class, name);
		return defaultValue(long.class);
	}

	protected final float floatParam(String name) {
		routesModuleBuilder.captureSimpleParam(Float.class, name);
		return defaultValue(float.class);
	}

	protected final double doubleParam(String name) {
		routesModuleBuilder.captureSimpleParam(Double.class, name);
		return defaultValue(double.class);
	}

	protected final char charParam(String name) {
		routesModuleBuilder.captureSimpleParam(Character.class, name);
		return defaultValue(char.class);
	}

	protected final boolean booleanParam(String name) {
		routesModuleBuilder.captureSimpleParam(Boolean.class, name);
		return defaultValue(boolean.class);
	}

	protected final String stringParam(String name) {
		routesModuleBuilder.captureSimpleParam(String.class, name);
		return "";
	}

	protected final byte byteParam(String name, byte defaultValue) {
		routesModuleBuilder.captureSimpleParam(Byte.class, name, defaultValue);
		return defaultValue(byte.class);
	}

	protected final short shortParam(String name, short defaultValue) {
		routesModuleBuilder.captureSimpleParam(Short.class, name, defaultValue);
		return defaultValue(short.class);
	}

	protected final int intParam(String name, int defaultValue) {
		routesModuleBuilder.captureSimpleParam(Integer.class, name, defaultValue);
		return defaultValue(int.class);
	}

	protected final long longParam(String name, long defaultValue) {
		routesModuleBuilder.captureSimpleParam(Long.class, name, defaultValue);
		return defaultValue(long.class);
	}

	protected final float floatParam(String name, float defaultValue) {
		routesModuleBuilder.captureSimpleParam(Float.class, name, defaultValue);
		return defaultValue(float.class);
	}

	protected final double doubleParam(String name, double defaultValue) {
		routesModuleBuilder.captureSimpleParam(Double.class, name, defaultValue);
		return defaultValue(double.class);
	}

	protected final char charParam(String name, char defaultValue) {
		routesModuleBuilder.captureSimpleParam(Character.class, name, defaultValue);
		return defaultValue(char.class);
	}

	protected final boolean booleanParam(String name, boolean defaultValue) {
		routesModuleBuilder.captureSimpleParam(Boolean.class, name, defaultValue);
		return defaultValue(boolean.class);
	}

	protected final String stringParam(String name, String defaultValue) {
		routesModuleBuilder.captureSimpleParam(String.class, name, defaultValue);
		return "";
	}

	protected final <T> T param(Class<T> type, String name) {
		routesModuleBuilder.captureComplexParam(type, name);
		return null;
	}

	protected final byte constant(byte value) {
		routesModuleBuilder.captureConstant(Byte.class, value);
		return value;
	}

	protected final short constant(short value) {
		routesModuleBuilder.captureConstant(Short.class, value);
		return value;
	}

	protected final int constant(int value) {
		routesModuleBuilder.captureConstant(Integer.class, value);
		return value;
	}

	protected final long constant(long value) {
		routesModuleBuilder.captureConstant(Long.class, value);
		return value;
	}

	protected final float constant(float value) {
		routesModuleBuilder.captureConstant(Float.class, value);
		return value;
	}

	protected final double constant(double value) {
		routesModuleBuilder.captureConstant(Double.class, value);
		return value;
	}

	protected final char constant(char value) {
		routesModuleBuilder.captureConstant(Character.class, value);
		return value;
	}

	protected final boolean constant(boolean value) {
		routesModuleBuilder.captureConstant(Boolean.class, value);
		return value;
	}

	protected final String constant(String value) {
		routesModuleBuilder.captureConstant(String.class, value);
		return value;
	}

	protected final HttpServletRequest request() {
		routesModuleBuilder.captureRequest();
		return null;
	}

	protected final HttpServletRequest response() {
		routesModuleBuilder.captureResponse();
		return null;
	}

	//	public void serveResource(String urlPrefix, Class<? extends Resource> controller) {
	//		
	//	}
	//	
	//	public void serveCRUD(String urlPrefix, Class<? extends CRUD> controller) {
	//		
	//	}

	public interface ControllerBindingBuilder {
		<T> T with(Class<T> controller);
	}

	public interface MethodBindingBuilder extends ControllerBindingBuilder {
		ControllerBindingBuilder method(Method method);

		ControllerBindingBuilder methods(Method method, Method... methods);

		ControllerBindingBuilder methods(Set<Method> methods);
	}
}
